package com.futvan.z.framework.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.FileUtils;

import com.futvan.z.framework.common.bean.Code;
import com.futvan.z.framework.common.bean.Result;
public class FileUtil {
	/**
	 * 获取文件MD5码，如果出错返回为空
	 * @param path
	 * @return MD5
	 */
	public static String getFileMD5(String path) {
		String result = "";
		try {
			if(!"".equals(path) && path!=null) {
				File fpath = new File(path);
				result = DigestUtils.md5Hex(new FileInputStream(fpath));
			}
		} catch (Exception e) {
		}
		return result;
	}
	
	/**
	 * 将图片流读出为图片
	 * 
	 * @param inputStream
	 * @param path
	 */
	private static void readBlob(InputStream inputStream, String path,String filename) {
		try {
			//判断目录是否存在，如果不存在自动创建
			mkdirs(path);
			FileOutputStream fileOutputStream = new FileOutputStream(path+filename);
			byte[] buffer = new byte[1024];
			int len = 0;
			while ((len = inputStream.read(buffer)) != -1) {
				fileOutputStream.write(buffer, 0, len);
			}
			inputStream.close();
			fileOutputStream.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}


	/**
	 * 创建目录
	 * @param path
	 */
	public static void mkdirs(String path){
		File dir = new File(path);
		// 判断文件目录是否存在
		if (!dir.exists() && !dir.isDirectory()) {
			//自动创建多级目录
			dir.mkdirs();
		}
	}

	/**
	 * 创建文件(文本类)
	 * 
	 * @param FilePath
	 *            文件全路径
	 * @param TXTvalue
	 *            文本内容
	 * @throws Exception
	 */
	public static void createrTXT(String FilePath, String TXTvalue)
			throws Exception {
		if ("".equals(FilePath) || FilePath == null) {
			return;
		}
		File file = new File(FilePath);
		// 如果找到相同的文件，执行删除
		if (file.exists() && file.isFile()) {
			file.delete();
		}
		file.createNewFile();
		if (!"".equals(TXTvalue) && TXTvalue != null) {
			writeTXT(FilePath, TXTvalue, "");
		}
	}

	/**
	 * 打开文件
	 * 
	 * @param FilePath
	 *            文件路径
	 * @throws Exception
	 */
	public static void OpenFile(String FilePath) throws Exception {
		Runtime.getRuntime().exec(
				"cmd /c start \"\" \""
						+ FilePath.replaceAll("\\\\", "\\\\\\\\") + "\"");
	}

	/**
	 * 文本文件写入信息
	 * 
	 * @param FilePath
	 * @param value
	 * @throws Exception
	 */
	public static void writeTXT(String FilePath, String value, String encoding)
			throws Exception {
		File f = new File(FilePath);
		if (!f.exists()) {
			f.createNewFile();
		}
		if ("".equals(encoding) || encoding == null) {
			encoding = "UTF-8";
		}
		OutputStreamWriter write = new OutputStreamWriter(new FileOutputStream(
				f), encoding);
		BufferedWriter writer = new BufferedWriter(write);
		writer.write(value);
		writer.close();
	}

	/**
	 * 获取文件文本信息
	 * 
	 * @param filePath
	 *            路径
	 * @param encoding
	 *            编码格式 GBK UTF-8 GB2312
	 * @return StringBuffer
	 * @throws Exception
	 */
	public static String readFileTXT(String filePath, String encoding) throws Exception {
		StringBuffer returnvalue = new StringBuffer();
		if ("".equals(encoding) || encoding == null) {
			encoding = "UTF-8";
		}
		File file = new File(filePath);
		if (file.isFile() && file.exists()) { // 判断文件是否存在
			InputStreamReader read = new InputStreamReader(new FileInputStream(
					file), encoding);
			BufferedReader bufferedReader = new BufferedReader(read);
			String lineTxt = null;
			while ((lineTxt = bufferedReader.readLine()) != null) {
				returnvalue.append(lineTxt);
			}
			read.close();
		}
		return returnvalue.toString();
	}

	/**
	 * 数据压缩
	 * 
	 * @param data
	 * @return
	 * @throws Exception
	 * 
	 * 
	 *             实例： String inputStr =
	 *             "owolf@zlex.orgzlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org"
	 *             ;
	 * 
	 *             System.err.println("压缩前:\t" + inputStr); byte[] input =
	 *             inputStr.getBytes(); System.err.println("压缩前长度:\t" +
	 *             input.length);
	 * 
	 * 
	 *             System.err.println(); byte[] data = FileUtil.compress(input);
	 *             System.err.println("压缩后长度:\t" + data.length);
	 *             System.err.println();
	 * 
	 *             byte[] output = FileUtil.decompress(data); String outputStr =
	 *             new String(output); System.err.println("解压后:\t" + outputStr);
	 *             System.err.println("解压后长度:\t" + output.length);
	 * 
	 * 
	 * 
	 */
	public static byte[] compress(byte[] data) throws Exception {
		byte[] output = null;
		ByteArrayInputStream bais = new ByteArrayInputStream(data);
		ByteArrayOutputStream baos = new ByteArrayOutputStream();

		// 压缩
		GZIPOutputStream gos = new GZIPOutputStream(baos);
		int count;
		byte dataByte[] = new byte[data.length];
		while ((count = bais.read(dataByte, 0, data.length)) != -1) {
			gos.write(dataByte, 0, count);
		}
		gos.finish();
		gos.flush();
		gos.close();

		output = baos.toByteArray();
		baos.flush();
		baos.close();
		bais.close();
		return output;
	}

	/**
	 * 数据解压缩
	 * 
	 * @param data
	 * @return
	 * @throws Exception
	 */
	public static byte[] decompress(byte[] data) throws Exception {
		byte[] output = null;
		ByteArrayInputStream bais = new ByteArrayInputStream(data);
		ByteArrayOutputStream baos = new ByteArrayOutputStream();

		// 解压缩
		GZIPInputStream gis = new GZIPInputStream(bais);
		int count;
		byte dataByte[] = new byte[data.length];
		while ((count = gis.read(dataByte, 0, data.length)) != -1) {
			baos.write(dataByte, 0, count);
		}
		gis.close();

		output = baos.toByteArray();

		baos.flush();
		baos.close();

		bais.close();
		return output;
	}

	/**
	 * 遍历文件夹
	 * 
	 * @param strPath
	 *            目录
	 */
	public static void selectFilePath(String FilePath) {
		File dir = new File(FilePath);
		File[] files = dir.listFiles();

		if (files == null)
			return;
		for (int i = 0; i < files.length; i++) {
			if (files[i].isDirectory()) {
				selectFilePath(files[i].getAbsolutePath());
			} else {
				// 获取文件名(包含目录)
				String strFileName = files[i].getAbsolutePath().toLowerCase();
			}
		}
	}


	/**
	 * 递归删除目录下的所有文件及子目录下所有文件
	 * 
	 * @param dir
	 *            将要删除的文件目录
	 * @return boolean Returns "true" if all deletions were successful. If a
	 *         deletion fails, the method stops attempting to delete and returns
	 *         "false".
	 */
	public static boolean deleteDir(File dir) {
		if (dir.isDirectory()) {
			String[] children = dir.list();
			// 递归删除目录中的子目录下
			for (int i = 0; i < children.length; i++) {
				boolean success = deleteDir(new File(dir, children[i]));
				if (!success) {
					return false;
				}
			}
		}
		// 目录此时为空，可以删除
		return dir.delete();
	}

	/**
	 * 移动文件
	 * 
	 * @param Path
	 *            文件
	 */
	public static void moveFile(String Path, String toPath) {
		// File (or directory) to be moved 
		File file = new File(Path); 

		// Destination directory 
		File dir = new File(toPath); 

		// Move file to new directory 
		file.renameTo(new File(dir, file.getName())); 
	}

	/**
	 * 复制单个文件
	 * @param oldPath String 原文件路径如：c:/fqf.txt
	 * @param newPath String 复制后路径如：f:/fqf.txt
	 */
	public static void copyFile(String oldPath, String newPath)
	{
		try
		{
			int bytesum = 0;
			int byteread = 0;
			File oldfile = new File(oldPath);
			if (oldfile.exists())
			{
				//文件存在时
				InputStream inStream = new FileInputStream(oldPath); //读入原文件
				FileOutputStream fs = new FileOutputStream(newPath);
				byte[] buffer = new byte[1444];
				while ( (byteread = inStream.read(buffer)) != -1)
				{
					bytesum += byteread; //字节数文件大小
					fs.write(buffer, 0, byteread);
				}
				inStream.close();
			}
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}
	
	/**
	 * 复制文件夹
	 * @throws Exception 
	 */
	public static void copyFolder(String resource, String target) throws Exception{
		File resourceFile = new File(resource);
		if (!resourceFile.exists()) {
			throw new Exception("源目标路径：[" + resource + "] 不存在...");
		}
		File targetFile = new File(target);
		if (!targetFile.exists()) {
			throw new Exception("存放的目标路径：[" + target + "] 不存在...");
		}

		// 获取源文件夹下的文件夹或文件
		File[] resourceFiles = resourceFile.listFiles();

		for (File file : resourceFiles) {

			File file1 = new File(targetFile.getAbsolutePath() + File.separator + resourceFile.getName());
			// 复制文件
			if (file.isFile()) {
				// 在 目标文件夹（B） 中 新建 源文件夹（A），然后将文件复制到 A 中
				// 这样 在 B 中 就存在 A
				if (!file1.exists()) {
					file1.mkdirs();
				}
				File targetFile1 = new File(file1.getAbsolutePath() + File.separator + file.getName());
				copyFile(file, targetFile1);
			}
			// 复制文件夹
			if (file.isDirectory()) {// 复制源文件夹
				String dir1 = file.getAbsolutePath();
				// 目的文件夹
				String dir2 = file1.getAbsolutePath();
				copyFolder(dir1, dir2);
			}
		}
	}
	
	public static void copyFile(File resource, File target) throws Exception {
		// 输入流 --> 从一个目标读取数据
		// 输出流 --> 向一个目标写入数据

		long start = System.currentTimeMillis();

		// 文件输入流并进行缓冲
		FileInputStream inputStream = new FileInputStream(resource);
		BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);

		// 文件输出流并进行缓冲
		FileOutputStream outputStream = new FileOutputStream(target);
		BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);

		// 缓冲数组
		// 大文件 可将 1024 * 2 改大一些，但是 并不是越大就越快
		byte[] bytes = new byte[1024 * 2];
		int len = 0;
		while ((len = inputStream.read(bytes)) != -1) {
			bufferedOutputStream.write(bytes, 0, len);
		}
		// 刷新输出缓冲流
		bufferedOutputStream.flush();
		//关闭流
		bufferedInputStream.close();
		bufferedOutputStream.close();
		inputStream.close();
		outputStream.close();

		long end = System.currentTimeMillis();

	}
	
	/**
     * Mapped File way MappedByteBuffer 可以在处理大文件时，提升性能
     * @param filename
     * @return
     * @throws IOException
     */
    public static byte[] getBytes(File file) throws IOException {
        FileChannel fc = null;
        try {
            fc = new RandomAccessFile(file, "r").getChannel();
            MappedByteBuffer byteBuffer = fc.map(FileChannel.MapMode.READ_ONLY, 0,fc.size()).load();
            byte[] result = new byte[(int) fc.size()];
            if (byteBuffer.remaining() > 0) {
                byteBuffer.get(result, 0, byteBuffer.remaining());
            }
            return result;
        } catch (IOException e) {
            e.printStackTrace();
            throw e;
        } finally {
            try {
                fc.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

	/**
	 * 获得指定文件的byte数组
	 * @throws IOException 
	 */
	public static byte[] getBytes(String filePath) throws IOException {
		return getBytes(new File(filePath));
	}
	

	/**
	 * 根据byte数组，生成文件
	 */
	public static void getFile(byte[] bfile, String filePath, String fileName) {
		BufferedOutputStream bos = null;
		FileOutputStream fos = null;
		File file = null;
		try {
			File dir = new File(filePath);
			if (!dir.exists() && dir.isDirectory()) {// 判断文件目录是否存在
				dir.mkdirs();
			}
			file = new File(filePath + "\\" + fileName);
			fos = new FileOutputStream(file);
			bos = new BufferedOutputStream(fos);
			bos.write(bfile);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (bos != null) {
				try {
					bos.close();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
			if (fos != null) {
				try {
					fos.close();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
		}
	}
	
	/**
	 * 判读目标是否为空
	 * @param path
	 * @return
	 */
	public static boolean dirsIsNull(String path) {
		boolean result = false;
		if(path!=null && !"".equals(path) && !"null".equals(path) && !"NULL".equals(path) && !"Null".equals(path) && !"NuLL".equals(path)) {
			File file = new File(path);
			//判读是否是目录
			if(file.isDirectory()){
				if(file.list().length<=0){
					result = true;
				}
			}
		}
		return result;
	}
}
